////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    SunkenTreasureGuts.cpp                                       //
//  Developer:   Lynn Akers                                                   //
//  Create date: 10/11/2005                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class implementation for the slot gut of the     //
//               Australian Slot machine called Sunken Treasure.              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2005 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#include "SunkenTreasureGuts.h"

////////////////////////////////////////////////////////////////////////////
/// SunkenTreasureGuts::m_aLineWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by wheel icon and then count.  So to get the
/// SpinResult for 5 Anchors, use the following code snippet:
///
///		SpinResult result = m_aLineWinSpinResults[ ICON_ANCHOR ][ 5 ];
///
/// In this example result would be set to EVT_FIVE_ANCHORS.
////////////////////////////////////////////////////////////////////////////
SunkenTreasureGuts::SpinResult SunkenTreasureGuts::m_aLineWinSpinResults[NUM_VALID_ICONS][6] = 
{
// Number of icons:		  0				1					2					3						4					5
/* ICON_NINE */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_NINE,			EVT_FOUR_NINE,		EVT_FIVE_NINE		},
/* ICON_TEN */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_TEN,			EVT_FOUR_TEN,		EVT_FIVE_TEN		},
/* ICON_JACK */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_JACK,			EVT_FOUR_JACK,		EVT_FIVE_JACK		},
/* ICON_QUEEN */		{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_QUEEN,		EVT_FOUR_QUEEN,		EVT_FIVE_QUEEN		},
/* ICON_KING */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_KING,			EVT_FOUR_KING,		EVT_FIVE_KING		},
/* ICON_ACE */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_THREE_ACE,			EVT_FOUR_ACE,		EVT_FIVE_ACE		},
/* ICON_ANCHOR */		{ EVT_LOSER,	EVT_LOSER,			EVT_TWO_ANCHOR,		EVT_THREE_ANCHOR,		EVT_FOUR_ANCHOR,	EVT_FIVE_ANCHOR		},
/* ICON_CORAL */		{ EVT_LOSER,	EVT_LOSER,			EVT_TWO_CORAL,		EVT_THREE_CORAL,		EVT_FOUR_CORAL,		EVT_FIVE_CORAL		},
/* ICON_FISH */			{ EVT_LOSER,	EVT_LOSER,			EVT_TWO_FISH,		EVT_THREE_FISH,			EVT_FOUR_FISH,		EVT_FIVE_FISH		},
/* ICON_TREASURE */		{ EVT_LOSER,	EVT_ONE_TREASURE,	EVT_TWO_TREASURE,	EVT_THREE_TREASURE,		EVT_FOUR_TREASURE,	EVT_FIVE_TREASURE	},
/* ICON_SHIP */			{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_LOSER,				EVT_LOSER,			EVT_LOSER			},
/* ICON_DIVER */		{ EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_LOSER,				EVT_LOSER,			EVT_LOSER			}
};
        
////////////////////////////////////////////////////////////////////////////
/// SunkenTreasureGuts::m_aScatterWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by icon count only, since Ships are the only
/// scatter win.  So to get the SpinResult for 5 Ships, use the
/// following code snippet:
///
///		SpinResult result = m_aScatterWinSpinResults[ 5 ];
///
/// In this example result would be set to EVT_FIVE_SHIP.
////////////////////////////////////////////////////////////////////////////
SunkenTreasureGuts::SpinResult SunkenTreasureGuts::m_aScatterWinSpinResults[6] = 
{
	// ICON_SHIP			   Number of Icons
	EVT_LOSER,				// 0
	EVT_SCATTER_NEAR_MISS,	// 1
	EVT_TWO_SHIP,			// 2	
	EVT_THREE_SHIP,			// 3
	EVT_FOUR_SHIP,			// 4
	EVT_FIVE_SHIP			// 5
};

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::SunkenTreasureGuts()   
///
/// This is the default constructor for the class.
////////////////////////////////////////////////////////////////////////////
SunkenTreasureGuts::SunkenTreasureGuts()
{
	// If this doesn't compile it means that someone probably added
	// another icon type but did not update the
	// m_aLineWinSpinResults array. 
	C_ASSERT( countof( m_aLineWinSpinResults ) == NUM_VALID_ICONS );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::~SunkenTreasureGuts()
///
/// Destructor for SunkenTreasureGuts. 
////////////////////////////////////////////////////////////////////////////
SunkenTreasureGuts::~SunkenTreasureGuts()
{
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::classifyStops()   
///
/// @param   stops      The array of stop positions for the line.
/// @param   bet        The value of the line bet.
/// @param   line       The index of the line.
///
/// @return	 uint8      A payout from the SpinResult enumeration as a uint8.    
///
/// This helper method is used to calculate the payout on a line.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::classifyStops( SpinLine* spinline, uint8* stops, uint8 bet, uint8 line,
	uint8& rtnresult, uint8& multiplier )
{
	// Keep up with whether or not we have a substitution on the rtnresult.
	bool bSubstitution = false;

	// The icon we are testing for.
	uint8 testIcon = getIcon( getGameModeId(), 0, stops[ 0 ] )->iconid;

	int i;

	// Loop through the remaining reels until the streak is over
	for ( i = 1; i < getReelCount(); i++ )
    {
		// See what this icon is.
		uint8 currentIcon = getIcon( getGameModeId(), i, stops[ i ] )->iconid;

		// If the current icon is a Diver...
		if ( currentIcon == ICON_DIVER )
		{
			if ( testIcon == ICON_SHIP )
			{
				// diver cannot substitute for ship so break out of the loop
				break;
			}
			else
			{
				// use diver as a substitution symbol and continue on.
				bSubstitution = true;
				continue;
			}
		}

		// If the current icon is not the test icon...
        if ( currentIcon != testIcon )
        {
			// then the streak is over so break out of the loop
			break;
        }
    }

	// Use the array to look up the spin result for i testIcons.
	rtnresult = lookupLineWinSpinResult( testIcon, i );

	// If we did actually have a substitution and a winning spin...
	if ( bSubstitution && rtnresult != EVT_LOSER )
	{
		// then add a note and change the multiplier.
		spinline->addNote( NOTE_DIVER_SUBSTITUTION );
		multiplier = MULTIPLIER_DIVER_SUBSTITUTION;
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn		SunkenTreasureGuts::tryForJackpot()
///
///	This function tries to win the jackpot and adds the scatter if we hit
/// the jackpot.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::tryForJackpot( SlotSpin* spin )
{
	// If we are in the first paid spin (NOT a bonus spin)...
	if ( getGameModeId() == MODE_NORMAL ) 
	{
		// then try for the Random Progressive Jackpot
		// If we hit the jackpot...
		if ( getRandomProgressiveJackpotResult( spin->getSpinLineCount() ) || 
			m_bForceRandomJackpot)
		{
			// then add a jackpot scatter to the spin.
			spin->addScatter( 0,
				getPayout( EVT_RANDOM_PROGRESSIVE_WINNER )->payoutAmount, 1,
				true, EVT_RANDOM_PROGRESSIVE_WINNER, 0 );
		}
    }
}

////////////////////////////////////////////////////////////////////////////
/// @fn		SunkenTreasureGuts::getScatterWinResult()
///
/// @param   spin				The spin we are evaluating.
/// @param   et					The direction that we should use when we evaluate the scatter.
/// @param   scatterPositions	An output parameter that contains a bit mask for the icon positions.
///
/// @return	 SpinResult			A payout from the SpinResult enumeration.
///
///	This function looks for scatter wins.  This game supports "left to right"
/// and "right to left".
////////////////////////////////////////////////////////////////////////////
SunkenTreasureGuts::SpinResult SunkenTreasureGuts::getScatterWinResult( SlotSpin* spin, int32& scatterPositions ) const
{
	// Keep up with how many scatter icons we found.
	uint8 numShipIcons = 0;

	// Loop through each reel.
  	for( int reel = 0; reel < getReelCount(); reel++ )
	{
		// The position bit for the current icon in case it needs to be stored in a mask.
		uint8 position = reel;

		// Loop through each row in the wheel house.
		for( int row = 0; row < 3; row++ )
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel,
				spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;
			
			// If the icon is a Ship...
			if ( currentIcon == ICON_SHIP )
			{
				// then increase the Ship count
				numShipIcons++;

				// Set the bit in the position mask for this stop.
				scatterPositions |= 1 << position;
			}

			// Move to the next bit in the position mask.
            position += 5;
		}
	}

	// Use the array to look up the spin result.
	return lookupScatterWinSpinResult( numShipIcons );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::evaluateScatterWin()
///
/// This function determines if the current spin wins a scatter payment and
/// adds the scatter.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::evaluateScatterWin( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions )
{
	// If we got the scatter win (or almost got it)
	if ( srScatterResult != EVT_LOSER )
	{
		// Get the base payout for the scatter.
		int32 nPayout = getPayout( srScatterResult )->payoutAmount;
		
		// Scatters payout based on the total bet, so factor in the number of bet lines.
		nPayout *= spin->getSpinLineCount();

		int32 multiplier = 1;


		// During free spin feature there are multipliers applied.
		if ( getGameModeId() == MODE_FREE_SPIN )
		{
			multiplier *= getFeatureGameMultiplier();
		}        

		// Add the payout to the total win for this spin.
		increaseTotalWin( nPayout * multiplier );
    
		// Add a scatter to the spin.
		SlotScatter* pScatter = spin->addScatter( scatterPositions,
			nPayout * getBetPerLine(), multiplier, false, srScatterResult, 0 );

        // In free spin mode, write a note about the variable multiplier.
		if ( getGameModeId() == MODE_FREE_SPIN )
		{
			pScatter->addNote(NOTE_FREE_SPIN_MULTIPLIER);
		}

	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::initializeBonusGame( int32 nTreasurePicks )
///
/// Setup the subgame data to start a new bonus game
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::initializeBonusGame( int32 nTreasurePicks )
{
	setFeatureGameMultiplier(MULTIPLIER_FREE_SPIN);
	setTreasurePicksAwarded( nTreasurePicks );
	initializeBonusGameResultIndex();
	initializeCurrentTreasureIndex();
	setTreasureChestSelectedMask(0);
	for ( int32 nTreasurePick = 0; nTreasurePick < MAX_TREASURE_PICKS; ++nTreasurePick )
	{
		setTreasureChestForPick( nTreasurePick, 0 );
		setTreasureChestWinType( nTreasurePick, WIN_TYPE_NONE);
		setTreasureChestWinAmount( nTreasurePick, 0 ); 
		setTreasureChestJewelType( nTreasurePick, JEWEL_TYPE_NONE);
	}

	initializeJewelPicksAwarded();
	initializeCurrentJewelIndex();
	setJewelPickSelectedMask(0);
	for ( int32 nJewelPick = 0; nJewelPick < MAX_JEWEL_PICKS; ++nJewelPick )
	{
		setJewelChestForPick( nJewelPick, 0 );
		setJewelPickWinAmount( nTreasurePick, 0 ); 
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::evaluateFeatureTrigger()
///
/// This function determines if the feature was triggered.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::evaluateFeatureTrigger( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions )
{
	// We need a spin result for the feature trigger.
	SpinResult srFeatureTrigger;

	// We need a place to keep up with how many picks to award.
	int32 nTreasurePicks = 0;

	// If the scatter result was a loser...
	if ( srScatterResult == EVT_LOSER )
	{
		// then we are done so just return now.
		return;
	}
	
	// Otherwise if the scatter result was a near miss or 2 Ships
	if ( srScatterResult == EVT_TWO_SHIP ||
		 srScatterResult == EVT_SCATTER_NEAR_MISS || 
		 srScatterResult == EVT_FEATURE_NEAR_MISS )
	{
		// then we will have a near miss for the feature.
		srFeatureTrigger = EVT_FEATURE_NEAR_MISS;
	}
	// Otherwise...
	else
	{
		switch ( srScatterResult )
		{
		case EVT_THREE_SHIP:
			nTreasurePicks = PICKS_FOR_THREE_SHIPS;
			break;

		case EVT_FOUR_SHIP:
			nTreasurePicks = PICKS_FOR_FOUR_SHIPS;
			break;

		case EVT_FIVE_SHIP:
			nTreasurePicks = PICKS_FOR_FIVE_SHIPS;
			break;

		default:
			ASSERT(!"Unknown scatter result!");
			break;
		}

		// we have a treasure dive feature
		srFeatureTrigger = EVT_TREASURE_DIVE_FEATURE;
	}

	// Add a scatter to the spin for the near miss or the feature trigger.
	spin->addScatter( scatterPositions, 0, 0, false,
		srFeatureTrigger, nTreasurePicks );

	initializeBonusGame( nTreasurePicks );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::classifyScatters( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This is an override of the framework method.  
/// It determines if the current spin merits free spins or scatter payments.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::classifyScatters( SlotSpin* spin )
{	
	// Try for the Random Progressive Jackpot
	tryForJackpot( spin );

	// Declare a local variable to track the scatter positions.
	int32 nScatterPositions = 0;

	// See what is the spin result.
	SpinResult spinResult = getScatterWinResult( spin, nScatterPositions );

	// Scatters payout any.
	evaluateScatterWin( spin, spinResult, nScatterPositions );

	// Now see if they triggered the feature.
	evaluateFeatureTrigger( spin, spinResult, nScatterPositions );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::getFeatureGameMultiplier() const 
///
/// @return  int32   The multiplier awarded for the feature.
///
/// This is an accessor mutator method to get the multiplier applied to the feature game.
////////////////////////////////////////////////////////////////////////////
int32 
SunkenTreasureGuts::getFeatureGameMultiplier() const
{
    return m_subGame->getData(SGDIDX_FEATURE_MULTIPLIER);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )   
///
/// @param	 nGameModeMultiplier    Returns the new multiplier based on the game mode.
/// @param   nNoteId                Returns the note Id associated with the game mode.
///
/// This helper method is get the game mode note and multiplier.
////////////////////////////////////////////////////////////////////////////
void 
SunkenTreasureGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )
{
	// During free spin feature there are multipliers applied.
    if ( getGameModeId() == MODE_FREE_SPIN )
    {
        nNoteId = NOTE_FREE_SPIN_MULTIPLIER;
        nGameModeMultiplier = getFeatureGameMultiplier();
    }
    else
    {
        SlotGuts::getGameModeMultiplierAndNoteId( nGameModeMultiplier, nNoteId );
    }
}
 
////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::setFeatureGameMultiplier(int32 nFeatureGameMultiplier) 
///
/// @param   nFeatureGameMultiplier  The multiplier awarded for the feature.
///
/// This is a mutator to set the multiplier applied to the feature game.
////////////////////////////////////////////////////////////////////////////
void 
SunkenTreasureGuts::setFeatureGameMultiplier(int32 nFeatureGameMultiplier)
{
    m_subGame->update(SGDIDX_FEATURE_MULTIPLIER,nFeatureGameMultiplier);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::setTreasureChestWinType( int32 nPick, int32 nWinType )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setTreasureChestWinType( int32 nPick, int32 nWinType )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

    m_subGame->update( SGDIDX_TREASURE_PICK_WIN_TYPE_1 +
		nPick * ( SGDIDX_TREASURE_PICK_WIN_TYPE_2 - SGDIDX_TREASURE_PICK_WIN_TYPE_1 ), nWinType );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasureChestWinType( int32 nPick ) const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasureChestWinType( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_TREASURE_PICK_WIN_TYPE_1 +
		nPick * ( SGDIDX_TREASURE_PICK_WIN_TYPE_2 - SGDIDX_TREASURE_PICK_WIN_TYPE_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::setTreasureChestJewelType( int32 nPick, int32 nJewelType )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setTreasureChestJewelType( int32 nPick, int32 nJewelType )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

    m_subGame->update( SGDIDX_TREASURE_PICK_JEWEL_TYPE_1 +
		nPick * ( SGDIDX_TREASURE_PICK_JEWEL_TYPE_2 - SGDIDX_TREASURE_PICK_JEWEL_TYPE_1 ), nJewelType );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasureChestJewelType( int32 nPick ) const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasureChestJewelType( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_TREASURE_PICK_JEWEL_TYPE_1 +
		nPick * ( SGDIDX_TREASURE_PICK_JEWEL_TYPE_2 - SGDIDX_TREASURE_PICK_JEWEL_TYPE_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::setTreasureChestWinAmount( int32 nChest, int32 nAmount )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setTreasureChestWinAmount( int32 nPick, int32 nAmount )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

    m_subGame->update( SGDIDX_TREASURE_PICK_WIN_AMOUNT_1 +
		nPick * ( SGDIDX_TREASURE_PICK_WIN_AMOUNT_2 - SGDIDX_TREASURE_PICK_WIN_AMOUNT_1 ), nAmount );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasureChestWinAmount( int32 nChest ) const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasureChestWinAmount( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_TREASURE_PICK_WIN_AMOUNT_1 +
		nPick * ( SGDIDX_TREASURE_PICK_WIN_AMOUNT_2 - SGDIDX_TREASURE_PICK_WIN_AMOUNT_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::setJewelPickWinAmount( int32 nChest, int32 nAmount )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setJewelPickWinAmount( int32 nPick, int32 nAmount )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_JEWEL_PICKS );

    m_subGame->update( SGDIDX_JEWEL_PICK_WIN_AMOUNT_1 +
		nPick * ( SGDIDX_JEWEL_PICK_WIN_AMOUNT_2 - SGDIDX_JEWEL_PICK_WIN_AMOUNT_1 ), nAmount );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getJewelPickWinAmount( int32 nChest ) const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getJewelPickWinAmount( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_JEWEL_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_JEWEL_PICK_WIN_AMOUNT_1 +
		nPick * ( SGDIDX_JEWEL_PICK_WIN_AMOUNT_2 - SGDIDX_JEWEL_PICK_WIN_AMOUNT_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::setTreasureChestForPick( int32 nPick, int32 nChest )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setTreasureChestForPick( int32 nPick, int32 nChest )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

    m_subGame->update( SGDIDX_TREASURE_PICK_POSITION_1 +
		nPick * ( SGDIDX_TREASURE_PICK_POSITION_2 - SGDIDX_TREASURE_PICK_POSITION_1 ), nChest );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasureChestForPick( int32 nPick ) const
///
/// Accessor for subgame data (nPick from 0 to 4)
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasureChestForPick( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_TREASURE_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_TREASURE_PICK_POSITION_1 +
		nPick * ( SGDIDX_TREASURE_PICK_POSITION_2 - SGDIDX_TREASURE_PICK_POSITION_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::setJewelChestForPick( int32 nPick, int32 nChest )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setJewelChestForPick( int32 nPick, int32 nChest )
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_JEWEL_PICKS );

    m_subGame->update( SGDIDX_JEWEL_PICK_POSITION_1 +
		nPick * ( SGDIDX_JEWEL_PICK_POSITION_2 - SGDIDX_JEWEL_PICK_POSITION_1 ), nChest );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getJewelChestForPick( int32 nPick ) const
///
/// Accessor for subgame data (nPick from 0 to 4)
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getJewelChestForPick( int32 nPick ) const
{
	ASSERT( nPick >= 0  &&  nPick <= MAX_JEWEL_PICKS );

	// Return the subgame data.
	return m_subGame->getData( SGDIDX_JEWEL_PICK_POSITION_1 +
		nPick * ( SGDIDX_JEWEL_PICK_POSITION_2 - SGDIDX_JEWEL_PICK_POSITION_1 ) );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void  SunkenTreasureGuts::updateTreasureChestSelectedMask( int32 nChest )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::updateTreasureChestSelectedMask( int32 nChest )
{
	ASSERT( nChest >= 0 && nChest < MAX_POSITIONS );

	int32 nMask = 1 << (1 + nChest) ;
	int32 nSelectedMask = getTreasureChestSelectedMask();
	nSelectedMask |= nMask;
	setTreasureChestSelectedMask( nSelectedMask );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::setTreasureChestSelectedMask( int32 nMask )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setTreasureChestSelectedMask( int32 nMask )
{
    m_subGame->update( SCGIDX_TREASURE_PICK_SELECTED_MASK, nMask );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasureChestSelectedMask() const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasureChestSelectedMask() const
{
	// Return the subgame data.
	return m_subGame->getData( SCGIDX_TREASURE_PICK_SELECTED_MASK );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void  SunkenTreasureGuts::updateTreasureChestSelectedMask( int32 nChest )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::updateJewelPickSelectedMask( int32 nChest )
{
	ASSERT( nChest >= 0 && nChest < MAX_POSITIONS );

	int32 nMask = 1 << (1 + nChest) ;
	int32 nSelectedMask = getJewelPickSelectedMask();
	nSelectedMask |= nMask;
	setJewelPickSelectedMask( nSelectedMask );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::setJewelPickSelectedMask( int32 nMask )
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
void  SunkenTreasureGuts::setJewelPickSelectedMask( int32 nMask )
{
    m_subGame->update( SCGIDX_JEWEL_PICK_SELECTED_MASK, nMask );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getJewelPickSelectedMask() const
///
/// Accessor for subgame data
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getJewelPickSelectedMask() const
{
	// Return the subgame data.
	return m_subGame->getData( SCGIDX_JEWEL_PICK_SELECTED_MASK );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasurePicksAwarded()
///
/// This helper method is used to get the subgame data that tracks how many
/// treasure chest picks have been awarded.
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasurePicksAwarded() const
{
	// Return the subgame data.
	return m_subGame->getData( SGDIDX_TREASURE_PICKS_AWARDED );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::setTreasurePicksAwarded( int32 nTreasurePicks )
///
/// This helper method is used to initialize the subgame data that tracks
/// which treasure chest pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::setTreasurePicksAwarded( int32 nTreasurePicks )
{
	// Initialize the subgame data to 0.
    m_subGame->update( SGDIDX_TREASURE_PICKS_AWARDED, nTreasurePicks );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getJewelPicksAwarded()
///
/// This helper method is used to get the subgame data that tracks which
/// treasure chest pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getJewelPicksAwarded() const
{
	// Return the subgame data.
	return m_subGame->getData( SGDIDX_JEWEL_PICKS_AWARDED );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::incrementJewelPicksAwarded()
///
/// This helper method is used to increment the subgame data that tracks
/// which treasure chest pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::incrementJewelPicksAwarded()
{
	// Get the current value and then add 1.
    m_subGame->update( SGDIDX_JEWEL_PICKS_AWARDED, getJewelPicksAwarded() + 1 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::initializeJewelPicksAwarded()
///
/// This helper method is used to initialize the subgame data that tracks
/// the number of jewel picks that have been awarded
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::initializeJewelPicksAwarded()
{
	// Initialize the subgame data to 0.
    m_subGame->update( SGDIDX_JEWEL_PICKS_AWARDED, 0 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getCurrentTreasureIndex()
///
/// This helper method is used to get the subgame data that tracks how many
/// treasure chest picks have been awarded.
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getCurrentTreasureIndex() const
{
	// Return the subgame data.
	return m_subGame->getData( SGDIDX_CURRENT_TREASURE_INDEX );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::incrementCurrentTreasureIndex()
///
/// This helper method is used to increment the subgame data that tracks
/// which treasure chest pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::incrementCurrentTreasureIndex()
{
	// Get the current value and then add 1.
    m_subGame->update( SGDIDX_CURRENT_TREASURE_INDEX, getCurrentTreasureIndex() + 1 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::initializeCurrentTreasureIndex()
///
/// This helper method is used to initialize the subgame data that tracks
/// which treasure chest pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::initializeCurrentTreasureIndex()
{
	// Initialize the subgame data to 0.
    m_subGame->update( SGDIDX_CURRENT_TREASURE_INDEX, 0 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getCurrentJewelIndex()
///
/// This helper method is used to get the subgame data that tracks
/// which jewel pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getCurrentJewelIndex() const
{
	// Return the subgame data.
	return m_subGame->getData( SGDIDX_CURRENT_JEWEL_INDEX );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::incrementCurrentJewelIndex()
///
/// This helper method is used to increment the subgame data that tracks
/// which jewel pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::incrementCurrentJewelIndex()
{
	// Get the current value and then add 1.
    m_subGame->update( SGDIDX_CURRENT_JEWEL_INDEX, getCurrentJewelIndex() + 1 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::initializeCurrentJewelIndex()
///
/// This helper method is used to initialize the subgame data that tracks
/// which jewel pick is currently being processed.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::initializeCurrentJewelIndex()
{
	// Initialize the subgame data to 0.
    m_subGame->update( SGDIDX_CURRENT_JEWEL_INDEX, 0 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getBonusGameResultIndex()
///
/// This helper method is used to get the subgame data that tracks which
/// index to use with addBonusGame
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getBonusGameResultIndex() const
{
	// Return the subgame data.
	return m_subGame->getData( SGDIDX_BONUS_GAME_RESULT_INDEX );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::postIncrementBonusGameResultIndex()
///
/// This helper method is used to increment the subgame data that tracks
/// which index to use with addBonusGame
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::postIncrementBonusGameResultIndex()
{
	int32 nBonusGameResultIndex = getBonusGameResultIndex();
    m_subGame->update( SGDIDX_BONUS_GAME_RESULT_INDEX, nBonusGameResultIndex + 1 );
	return nBonusGameResultIndex;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::initializeBonusGameResultIndex()
///
/// This helper method is used to initialize the subgame data that tracks
/// which index to use with addBonusGame
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::initializeBonusGameResultIndex()
{
	// Initialize the subgame data to 1.
    m_subGame->update( SGDIDX_BONUS_GAME_RESULT_INDEX, 1 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::isTreasureChestSelected( int32 nChest ) const
///
/// Has the treasure chest (0-7) already been selected?
////////////////////////////////////////////////////////////////////////////
bool  SunkenTreasureGuts::isTreasureChestSelected( int32 nChest ) const
{
	ASSERT( nChest >= 0 && nChest < MAX_POSITIONS );

	int32 nMask = 1 << (1 + nChest) ;
	int32 nSelectedMask = getTreasureChestSelectedMask();
	return ( (nMask & nSelectedMask) != 0 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 void SunkenTreasureGuts::isJewelChestSelected( int32 nChest ) const
///
/// Has the treasure chest (0-7) already been selected?
////////////////////////////////////////////////////////////////////////////
bool  SunkenTreasureGuts::isJewelChestSelected( int32 nChest ) const
{
	ASSERT( nChest >= 0 && nChest < MAX_POSITIONS );

	int32 nMask = 1 << (1 + nChest) ;
	int32 nSelectedMask = getJewelPickSelectedMask();
	return ( (nMask & nSelectedMask) != 0 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getTreasurePicksRemaining()
///
/// This helper method is used to get the subgame data that tracks how many
/// treasure chest picks are left to be processed
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getTreasurePicksRemaining() const
{
	int32 nPicks = getTreasurePicksAwarded();
	int32 nIndex = getCurrentTreasureIndex();
	int32 nRemaining = (nPicks > nIndex) ? nPicks - nIndex : 0;
	return nRemaining;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 int32 SunkenTreasureGuts::getJewelPicksRemaining()
///
/// This helper method is used to get the subgame data that tracks how many
/// jewel picks are left to be processed
////////////////////////////////////////////////////////////////////////////
int32 SunkenTreasureGuts::getJewelPicksRemaining() const
{
	int32 nPicks = getJewelPicksAwarded();
	int32 nIndex = getCurrentJewelIndex();
	int32 nRemaining = (nPicks > nIndex) ? nPicks - nIndex : 0;
	return nRemaining;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::awardFreeSpins()
///
/// The free spin counter cannot be updated until the bonus game is ready
/// to complete; otherwise the loadSavedGame logic can incorrectly
/// interpret a saved game as a 're-spin' since it already has free spins.
////////////////////////////////////////////////////////////////////////////
void
SunkenTreasureGuts::awardFreeSpins()
{
	int32 nFreeSpins = INITIAL_FREE_GAME_AWARD;

	int32 nMaxPicks = getTreasurePicksAwarded();

	for( int32 nPick = 0; nPick < nMaxPicks; ++nPick )
	{
		int32 nWinType = getTreasureChestWinType( nPick );
		if ( nWinType == WIN_TYPE_FREE_GAMES )
		{
			nFreeSpins += WIN_FREE_GAME_AWARD;
		}
	}

	if ( nFreeSpins )
	{
		incrementFreeSpins( nFreeSpins );
		setGameModeId(MODE_FREE_SPIN);
	}
	else if ( getFreeSpins() )
	{
		setGameModeId(MODE_FREE_SPIN);
	}
	else
	{
		setGameModeId( MODE_NORMAL);
	}

	setBonusGameState(BONUS_GAME_NONE);
	setGameCanComplete(true);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::processClientData()
///
/// @param   bonusGameType      The current type of bonus game.
/// @param   bonusDataCount     The number of integers passed from the client.
/// @param   bonusData			An array of integers passed from the client.
/// 
/// This is an override of the framework method.
/// 
////////////////////////////////////////////////////////////////////////////
bool8
SunkenTreasureGuts::processClientData(uint8 bonusGameType, int32 bonusDataCount, int32 *bonusData)
{
	// Start by assuming that we do not need to reply to this message
	bool8 bReply = false;

	if ( getBonusGameState() == BONUS_GAME_ACTIVE )
	{
		switch ( bonusGameType )
		{
			case BONUS_GAME_TREASURE_DIVE:
			{
				if ( bonusDataCount == 1 )
				{
					int32 nChest = *bonusData;

					if ( nChest >= 0 && nChest < MAX_POSITIONS )
					{
						if ( getTreasurePicksRemaining() == 0 )
						{
						}
						else if ( isTreasureChestSelected( nChest ) )
						{
							// Position already selected.  Log it.
						}
						else
						{
							// The state will change, so a reply is required
							bReply = true;

							// Record which treasure chest was picked
							int32 nPick = getCurrentTreasureIndex();
							setTreasureChestForPick( nPick, nChest );
							updateTreasureChestSelectedMask( nChest );

							// Determine the prize type associated with this Win
							int32 nRandomWin = getRandomValueFromProbabilityTable(PT_BONUS_PRIZE_AWARDED_PER_PICK_VALUE);

							// Note that wins are 1-based because 0 is reserved 
							// for WIN_TYPE_NONE, so convert to our enum range.
							int32 nWinType = 1 + nRandomWin;

							setTreasureChestWinType( nPick, nWinType );

							int nMultiplier = 0;

							int32 nWinAmount = 0;

							switch ( nWinType )
							{
								case WIN_TYPE_MULITPLIER_2:
									nMultiplier = 2;
									break;

								case WIN_TYPE_MULITPLIER_3:
									nMultiplier = 3;
									break;

								case WIN_TYPE_MULITPLIER_5:
									nMultiplier = 5;
									break;

								case WIN_TYPE_MULITPLIER_10:
									nMultiplier = 10;
									break;

								case WIN_TYPE_FREE_GAMES:
									addBonusGame(0, postIncrementBonusGameResultIndex(), 0, 0, 0, WIN_FREE_GAME_AWARD);
									break;
							}

							// If this line win is a multiplier then record the credits awarded
							if ( nMultiplier )
							{
								int32 basepayoutamount = getBetPerLine() * getNumLinesBet();
								int32 totalmultiplier = nMultiplier;

								// 3x award during free spins
								if ( getGameModeId() == MODE_FREE_SPIN )
								{
									totalmultiplier *= getFeatureGameMultiplier();
								}

								int32 totalbonuspayoutamount = basepayoutamount * totalmultiplier;
								nWinAmount = totalbonuspayoutamount;
								addBonusGame(0, postIncrementBonusGameResultIndex(), basepayoutamount, totalmultiplier, totalbonuspayoutamount, 0);
							}
							setTreasureChestWinAmount( nPick, nWinAmount );

							// The treasure chest may also award a prize.  
							int nRandomJewel = getRandomValueFromProbabilityTable(PT_BONUS_CHANCE_TO_REVEAL_JEWEL_VALUE);

							// The enumeration differs from the probability table 
							// because we want no prize (JEWEL_TYPE_NONE) to be index 0.
							//
							// Enum					Random Table
							// 0 JEWEL_TYPE_NONE		  2
							// 1 JEWEL_TYPE_BLUE          0
							// 2 JEWEL_TYPE_RED           1
							int nJewelType = (1 + nRandomJewel) % 3;

							setTreasureChestJewelType( nPick, nJewelType );
							if ( nJewelType != JEWEL_TYPE_NONE )
							{
								incrementJewelPicksAwarded();
							}

							incrementCurrentTreasureIndex();

							// if this was the last pick then wrap up the treasure dive
							if ( getTreasurePicksRemaining() == 0 )
							{
								if ( getJewelPicksRemaining() == 0 )
								{
									awardFreeSpins();
								}
							}
						}
					}
				}
			}
			break;

			case BONUS_GAME_JEWEL_PICK:
			{	
				if ( bonusDataCount == 1 )
				{
					int32 nChest = *bonusData;

					if ( nChest >= 0 && nChest < MAX_POSITIONS )
					{
						if ( getTreasurePicksRemaining() != 0 )
						{
						}
						else if ( getJewelPicksRemaining() == 0 )
						{
						}						
						else if ( isJewelChestSelected( nChest ) )
						{
							// Position already selected.  Log it.
						}
						else
						{
							// The state will change, so a reply is required
							bReply = true;

							// Record which treasure chest was picked
							int32 nJewelPick = getCurrentJewelIndex();
							setJewelChestForPick( nJewelPick, nChest );
							updateJewelPickSelectedMask( nChest );

							// Jewel picks are chosen in 'descending' order; i.e., the reverse
							// order from which they were awarded.
							int32 nJewelChestDescending = MAX_TREASURE_PICKS;
							for ( int32 nCount = 0; nCount <= nJewelPick; ++nCount)
							{
								do
								{
									--nJewelChestDescending;
								}
								while ( getTreasureChestJewelType(nJewelChestDescending) == JEWEL_TYPE_NONE );
							}

							ASSERT( nJewelChestDescending >= 0 );

							int nJewelType = getTreasureChestJewelType( nJewelChestDescending );

							int nMultiplier = 0;

							if ( nJewelType == JEWEL_TYPE_BLUE )
							{
								nMultiplier = getRandomValueFromProbabilityTable(PT_BONUS_BLUE_JEWEL_PRIZES_VALUE);
							}
							else if ( nJewelType == JEWEL_TYPE_RED )
							{
								nMultiplier = getRandomValueFromProbabilityTable(PT_BONUS_RED_JEWEL_PRIZES_VALUE);
							}
							else
							{
								// unknown jewel type!
								ASSERT(false);
							}

							int32 basepayoutamount = getBetPerLine() * getNumLinesBet();
							int32 totalmultiplier = nMultiplier;

							// 3x award during free spins
							if ( getGameModeId() == MODE_FREE_SPIN )
							{
								totalmultiplier *= getFeatureGameMultiplier();
							}


							int32 totalbonuspayoutamount = basepayoutamount * totalmultiplier;
							int32 nWinAmount = totalbonuspayoutamount;
							addBonusGame(1, postIncrementBonusGameResultIndex(), basepayoutamount, totalmultiplier, totalbonuspayoutamount, 0);
							setJewelPickWinAmount( nJewelPick, nWinAmount );

							incrementCurrentJewelIndex();

							// if this was the last pick then wrap up the jewel pick game
							if ( getJewelPicksRemaining() == 0 )
							{
								awardFreeSpins();
							}
						}
					}
				}
			}
			break;
		}
	}

	return bReply;
}





////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::isValidGuts()   
///
/// @return	 bool8      True if gut is valid.    
///
/// This helper method is used to see if the current gut ID is valid.
////////////////////////////////////////////////////////////////////////////
bool8 SunkenTreasureGuts::isValidGuts()
{
	// Make sure that the m_aLineWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	// Note:  we can't do this in the constructor because we have to call
	// getReelCount.
	ASSERT( countof( m_aLineWinSpinResults[0] ) == getReelCount( MODE_NORMAL ) + 1 );

	// Make sure that the m_aScatterWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 scatter icons.
	ASSERT( countof( m_aScatterWinSpinResults ) == getReelCount( MODE_NORMAL ) + 1 );

	// Now make sure that both game modes have the same number of reels.
	ASSERT( getReelCount( MODE_NORMAL ) == getReelCount( MODE_FREE_SPIN ) );

	// Finally just check to see if the gut is within the right range.
    return ( getGutsId() >= 1300 && getGutsId() < 1400 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::hasSavedGames()   
///
/// This helper method is a framework override that indicates this machine can have saved games.
////////////////////////////////////////////////////////////////////////////
bool8
SunkenTreasureGuts::hasSavedGames()
{
	return true;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::preSpinClassifyResults( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden to alter the reel stops for the respin feature.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::preSpinClassifyResults( SlotSpin* spin )
{
	SlotGuts::preSpinClassifyResults(spin);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 SunkenTreasureGuts::postSpinClassifyResults( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden to see if we can complete the game.
////////////////////////////////////////////////////////////////////////////
void SunkenTreasureGuts::postSpinClassifyResults( SlotSpin* spin )
{
	// If we have not reached the feature cap yet and we have feature rounds...
	if ( !getMaxPayoutAwarded() && getTreasurePicksRemaining() )
	{
		// The game can't complete until the bonus game is done.
		setGameCanComplete( false );
		setBonusGameState( BONUS_GAME_ACTIVE );
	}
}
